#include "InPerUartInit.h"

#define DEF_TAG "UartInit"

#define DEF_PER_UART_WRITE_MAX_LEN 2048

Com_s32 g_InPer_Uart_Fd = -1;
pthread_mutex_t g_InPer_Uart_Write_Mutex;

Com_s32 Ext_InPer_Uart_Fd(Com_void)
{
    return g_InPer_Uart_Fd;
}

Com_void Ext_InPer_Uart_Close(Com_void)
{
    pthread_mutex_destroy(&g_InPer_Uart_Write_Mutex);
    close(g_InPer_Uart_Fd);
}

Com_s32 InPer_Uart_Set_Opt(Com_s32 fd, Com_s32 nSpeed, Com_s32 nBits, Com_s8 nEvent, Com_s32 nStop)
{
    struct termios newtio, oldtio;

    if (tcgetattr(fd, &oldtio) != 0)
    {
        perror("SetupSerial");
        return -1;
    }

    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch (nBits)
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch (nEvent)
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }

    switch (nSpeed)
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }

    if (nStop == 1)
    {
        newtio.c_cflag &= ~CSTOPB;
    }
    else if (nStop == 2)
    {
        newtio.c_cflag |= CSTOPB;
    }

    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd, TCIOFLUSH);
    if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
    {
        perror("com set error");
        return -1;
    }

    PRT_DBG(DEF_TAG, "set done!\n");
    return 0;
}

Com_s32 InPer_Uart_Open(Com_void)
{
    static int fd = -1;

#if CMAKE_ANYKA_EV300L
    fd = open("/dev/ttySAK2", O_RDWR | O_NOCTTY | O_NDELAY);
#elif CMAKE_INGENIC_T41N
    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
#endif

    if (-1 == fd)
    {
        PRT_ERR(DEF_TAG, "Can't Open Serial Port\n");
        return (-1);
    }
    else
    {
        // printf("open ttySAK1 .....\n");
    }

    if (fcntl(fd, F_SETFL, 0) < 0)
    {
        PRT_ERR(DEF_TAG, "fcntl failed!\n");
    }
    else
    {
        PRT_INFO(DEF_TAG, "fcntl=%d\n", fcntl(fd, F_SETFL, 0));
    }

    if (isatty(STDIN_FILENO) == 0)
    {
        PRT_NORMAL("standard input is not a terminal device\n");
    }
    else
    {
        PRT_INFO(DEF_TAG, "isatty success!\n");
    }

    return fd;
}

Com_s32 Ext_InPer_Uart_Opt_Init(Com_void)
{
    Com_s32 speed;

#if CMAKE_SERIAL_BAUD_RATE_115200
    speed = 115200;
#else
    speed = 9600;
#endif

    if ((g_InPer_Uart_Fd = InPer_Uart_Open()) < 0)
    {
        perror("open port error");
        return -1;
    }

    if (InPer_Uart_Set_Opt(g_InPer_Uart_Fd, speed, 8, 'N', 1) < 0)
    {
        close(g_InPer_Uart_Fd);
        perror("set opt error");
        return -1;
    }

    pthread_mutex_init(&g_InPer_Uart_Write_Mutex, NULL);
    return 0;
}

Com_s32 Ext_InPer_Uart_Write(Com_pu8 buff, Com_u32 len)
{
    pthread_mutex_lock(&g_InPer_Uart_Write_Mutex);

    Com_s32 ret = -1;

    if (len > DEF_PER_UART_WRITE_MAX_LEN)
    {
        PRT_ERR(DEF_TAG, "error length!\n");
        goto exit;
    }

    if (g_InPer_Uart_Fd == -1)
    {
        PRT_ERR(DEF_TAG, "fd is error!\n");
        goto exit;
    }

    if (buff[3] == 0x0b)
    {
        PRT_INFO(DEF_TAG, "OTA MCU[%02x%02x%02x%02x]\n", buff[6], buff[7], buff[8], buff[9]);
    }
    else
    {
        PRT_INFO(DEF_TAG, "send->");
        Com_s32 j;

        for (j = 0; j < len; j++)
        {
            PRT_NORMAL("%02x", buff[j]);
        }
        PRT_NORMAL("\n");
    }

    ret = write(g_InPer_Uart_Fd, buff, len);
    usleep(10 * 1000);

    // PRT_DBG(DEF_TAG,"end of send\n");
exit:
    pthread_mutex_unlock(&g_InPer_Uart_Write_Mutex);
    return ret;
}
